package rensoft.portfolio.client.view.workslides;

import static com.google.gwt.query.client.GQuery.$;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.query.client.css.CSS;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;

import static cs.java.lang.Lang.SECOND;
import static cs.java.lang.Lang.doLater;
import static cs.java.lang.Lang.no;
import static cs.java.lang.Lang.schedule;

import cs.java.lang.HasService;
import cs.java.lang.Run;
import cs.java.lang.Lang.Work;
import cs.java.utility.RunConsolidator;



import static rensoft.gwt.client.lang.GwtLang.setFadeVisible;

import rensoft.gwt.client.event.EventFunction;
import rensoft.gwt.client.view.View;
import rensoft.portfolio.client.lib.view.ImageButton;
import rensoft.portfolio.client.model.titles.Page;
import rensoft.portfolio.client.model.titles.Title;
import rensoft.portfolio.client.model.titles.Titles;
import rensoft.portfolio.client.model.titles.Titles.TitleState;

public class WorksSlidesWidget extends View<IsWidget> {

  private static final int SLIDE_PERIOD = 3 * SECOND;

  private static final Binder uiBinder = GWT.create(Binder.class);
  @UiField
  Image currentImage;
  @UiField
  ImageButton controlNext;
  @UiField
  ImageButton controlPause;
  @UiField
  ImageButton controlPlay;
  @UiField
  ImageButton controlBack;
  @UiField
  FlowPanel imagePanel;
  @UiField
  FlowPanel controlsPlay;
  @UiField
  FlowPanel controls;

  @UiField
  Image loadingImage;
  private final Work changeTimer = schedule(SLIDE_PERIOD, new Run() {
    public void run() {
      onChangeTimeElapsed();
    }
  });

  private int currentIndex = 0;

  private final RunConsolidator runconsolide = new RunConsolidator(SECOND);

  private boolean paused;

  public WorksSlidesWidget() {
    initWidget(uiBinder.createAndBindUi(this));
    imagePanel.addDomHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        onImagePanelClick();
      }
    }, ClickEvent.getType());
  }

  @Override
  public void initialize(HasService app) {
    super.initialize(app);
    hide();
    $(currentImage, controls).hide();
    loadCurrentWork();
    if (no(getTitles().getOpenTitle())) doLater(1500, new Runnable() {
      public void run() {
        pause();
        $(asWidget()).fadeIn(3000);
      }
    });
    getTitles().addHandler(Titles.ON_CHANGE, new EventFunction<Title>() {
      public void run(Title value) {
        onTitleChange(value);
      }
    });
    controlPlay.addDomHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        onPlayClick();
      }
    }, ClickEvent.getType());
    controlPause.addDomHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        onPauseClick();
      }
    }, ClickEvent.getType());
    controlNext.addDomHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        onNextClick();
      }
    }, ClickEvent.getType());
    controlBack.addDomHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        onBackClick();
      }
    }, ClickEvent.getType());
    addMouseOverHandler(new MouseOverHandler() {
      public void onMouseOver(MouseOverEvent event) {
        if (!paused) $(controls).fadeIn();
      }
    });
    addMouseOutHandler(new MouseOutHandler() {
      public void onMouseOut(MouseOutEvent event) {
        if (!paused) $(controls).fadeOut();
      }
    });
  }

  public void pause() {
    paused = true;
    changeTimer.stop();
    $(controls).fadeIn();
    setFadeVisible(false, controlPause);
    $(controlPause).css(CSS.ZINDEX.with(0));
    setFadeVisible(true, controlsPlay);
    $(controlsPlay).css(CSS.ZINDEX.with(200));
  }

  public void show(final Page page) {
    currentIndex = getWorks().getIndex(page);
  }

  private void close() {
    changeTimer.stop();
    $(currentImage, loadingImage).fadeOut();
    $(asWidget()).fadeOut(100);
  }

  private Titles getTitles() {
    return get(Titles.class);
  }

  private Title getWorks() {
    return getTitles().getTitle(TitleState.products);
  }

  private void loadCurrentWork() {
    Page page = getWorks().getPage(currentIndex);
    loadingImage.setResource(page.getBigImage());
    loadingImage.setVisible(false);
    loadingImage.addStyleName("slideImage");
    $(loadingImage).fadeIn(1 * SECOND);
    $(currentImage).fadeOut(1 * SECOND);
    switchImages();
  }

  private void onBackClick() {
    runconsolide.invoke(new Run() {
      public void run() {
        if (currentIndex > 0)
          currentIndex--;
        else currentIndex = getWorks().getPageCount() - 1;
        loadCurrentWork();
      }
    });
  }

  private void onChangeTimeElapsed() {
    setNextIndex();
    loadCurrentWork();
  }

  private void onImagePanelClick() {
    getWorks().showPage(currentIndex);
    getTitles().open(TitleState.products);
  }

  private void onNextClick() {
    runconsolide.invoke(new Run() {
      public void run() {
        if (currentIndex < getWorks().getPageCount() - 1)
          currentIndex++;
        else currentIndex = 0;
        loadCurrentWork();
      }
    });
  }

  private void onPauseClick() {
    pause();
  }

  private void onPlayClick() {
    play();
  }

  private void onTitleChange(Title title) {
    if (no(title)) {
      open();
      loadCurrentWork();
      if (paused)
        pause();
      else play();
    } else close();
  }

  private void open() {
    doLater(QUICK_ANIMATION, new Runnable() {
      public void run() {
        $(asWidget()).fadeIn();
      }
    });
  }

  private void play() {
    paused = false;
    changeTimer.start();
    setFadeVisible(true, controlPause);
    $(controlPause).css(CSS.ZINDEX.with(200));
    setFadeVisible(false, controlsPlay);
    $(controlsPlay).css(CSS.ZINDEX.with(0));
  }

  private void setNextIndex() {
    if (currentIndex == getWorks().getPageCount() - 1)
      currentIndex = 0;
    else currentIndex++;
  }

  private void switchImages() {
    Image tmpCurrentImage = currentImage;
    currentImage = loadingImage;
    loadingImage = tmpCurrentImage;
  }

  interface Binder extends UiBinder<Widget, WorksSlidesWidget> {}
}
